export default class WWW {

    // 停止运作
    public static isStop: boolean = false;

    public static safetyCall(callback?: (...args: any) => void, target?: any, ...args: any) {
        if (callback) {
            if (target)
                callback.apply(target, args);
            else
                callback(args);
        }
    }

    /**
     * http Get 请求
     * @param url 
     * @param callback 
     * @param params 
     */
    public static async Get(url: string, callback?: (res: any, err: any) => void, target?: any, params?: { [key: string]: string }) {
        return new Promise((resolve, reject) => {

            let strParam = "";
            if (params) {
                for (var key in params) {
                    strParam += key + "=" + params[key] + "&";
                }
            }

            let xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                console.log("Get: readyState:" + xhr.readyState + " status:" + xhr.status);
                // 接收完毕
                if (xhr.readyState === 4 || xhr.readyState === 200) {
                    if (xhr.status >= 200 && xhr.status < 400) {
                        let respone = xhr.responseText;
                        // let rsp = JSON.parse(respone);
                        if (callback) {
                            if (target)
                                callback.apply(target, [respone, null]);
                            else
                                callback(respone, null);
                        }
                        resolve(respone);
                    } else {
                        if (callback != null) {
                            if (target)
                                callback.apply(target, [null, { status: xhr.status }]);
                            else
                                callback(null, { status: xhr.status });
                        }
                        resolve(null);
                    }
                }
            };

            xhr.withCredentials = true;
            xhr.open('GET', url, true);
            // xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
            // xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET, POST');
            // xhr.setRequestHeader('Access-Control-Allow-Headers', 'x-requested-with,content-type,authorization');
            // xhr.setRequestHeader("Content-Type", "application/json");
            xhr.timeout = 8000;// 8 seconds for timeout
            xhr.send(strParam);
        });
    }

    /**
     * http post 请求
     * @param url 
     * @param callback 
     * @param params 
     */
    public static async Post(url: string, callback?: (res: any, err: any) => void, target?: any, params?: { [key: string]: string }) {

        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                // 接收完毕
                if (xhr.readyState === 4 || xhr.readyState === 200) {
                    if (xhr.status >= 200 && xhr.status < 400) {
                        let respone = xhr.responseText;
                        if (callback) {
                            if (target)
                                callback.apply(target, [respone, null]);
                            else
                                callback(respone, null);
                        }
                        resolve(respone);
                    } else {
                        if (callback != null) {
                            if (target)
                                callback.apply(target, [null, { status: xhr.status }]);
                            else
                                callback(null, { status: xhr.status });
                        }
                        resolve(null);
                    }
                }
            };
            xhr.open('POST', url, true);
            // xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
            // xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET, POST');
            // xhr.setRequestHeader('Access-Control-Allow-Headers', 'x-requested-with,content-type');
            // xhr.setRequestHeader("Content-Type", "application/json");
            xhr.timeout = 8000;// 8 seconds for timeout

            if (params) {
                xhr.send(JSON.stringify(params));
            }
            else {
                xhr.send();
            }
        });
    }

    /**
     * 字符串转成Uint8Array
     * @param str 
     * @returns 
     */
    public static stringToUint8Array(str: string): Uint8Array {
        var arr = Array(str.length);
        for (var i = 0, j = str.length; i < j; ++i) {
            arr[i] = str.charCodeAt(i);
        }
        var tmpUint8Array = new Uint8Array(arr);
        return tmpUint8Array
    }


    public static stringToUint8Array2(str: string): Uint8Array {
        var len, c;
        len = str.length;
        var bytes = [];
        for (var i = 0; i < len; i++) {
            c = str.charCodeAt(i);
            if (c >= 0x010000 && c <= 0x10FFFF) {
                bytes.push(((c >> 18) & 0x07) | 0xF0);
                bytes.push(((c >> 12) & 0x3F) | 0x80);
                bytes.push(((c >> 6) & 0x3F) | 0x80);
                bytes.push((c & 0x3F) | 0x80);
            } else if (c >= 0x000800 && c <= 0x00FFFF) {
                bytes.push(((c >> 12) & 0x0F) | 0xE0);
                bytes.push(((c >> 6) & 0x3F) | 0x80);
                bytes.push((c & 0x3F) | 0x80);
            } else if (c >= 0x000080 && c <= 0x0007FF) {
                bytes.push(((c >> 6) & 0x1F) | 0xC0);
                bytes.push((c & 0x3F) | 0x80);
            } else {
                bytes.push(c & 0xFF);
            }
        }
        return new Uint8Array(bytes);
    }

    public static uint8ArrayToString(fileData: Uint8Array): string {
        var dataString = "";
        for (var i = 0; i < fileData.length; i++) {
            dataString += String.fromCharCode(fileData[i]);
        }
        return dataString
    }

    /**
     * Post请求 参数是Protobuf
     * @param url 
     * @param data 
     * @param encode 
     * @param decode 
     * @param handleError 
     * @param callback 
     * @param target 
     * @param isLog 
     * @returns 
     */
    public static PostProtoEx(url: string, data: any, encode: Function, decode: Function, handleError: Function, callback: Function, target: any, isLog: boolean = true) {
        // 停止发送事件
        if (WWW.isStop) {
            callback.call(target, null);
            return;
        }

        if (isLog)
            console.log("请求：" + url + "=>" + JSON.stringify(data));


        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            // 接收完毕
            if (xhr.readyState === 4 || xhr.readyState === 200) {
                if (xhr.status >= 200 && xhr.status < 400) {
                    let respone = xhr.response;
                    let bytes = new Uint8Array(respone);
                    let resq: any;

                    try {
                        resq = decode(bytes);
                        if (resq)
                            resq['url'] = url;
                    } catch (error) {
                        console.error("协议解释失败：" + error);
                        callback.call(target, null);
                        return;
                    }

                    if (isLog)
                        console.log("请求成功：" + url + "=>" + JSON.stringify(resq));

                    if (handleError && handleError(resq)) {
                        callback.call(target, null);
                        return;
                    }

                    callback.call(target, resq);

                } else {
                    if (handleError && handleError(null)) {
                        callback.call(target, null);
                        return;
                    }

                    if (isLog)
                        console.log("请求失败：" + url + "=>" + xhr.status);

                    callback.call(target, null);
                }
            }
        };
        xhr.open('POST', url, true);
        xhr.responseType = "arraybuffer";
        // xhr.setRequestHeader('Access-Control-Allow-Credentials', 'true');
        // xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
        // xhr.setRequestHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
        // xhr.setRequestHeader('Access-Control-Allow-Headers', 'Content-Type,AccessToken,X-CSRF-Token, Authorization,Token,X-Requested-With');
        // xhr.setRequestHeader("Content-Type", "application/x-protobuf");
        xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        // xhr.timeout = 8000;// 8 seconds for timeout

        let bytes = encode(data).finish();
        let blob = new Blob([bytes], { type: "buffer" });
        xhr.send(blob);

    }


    /**
     * Post请求 参数是Protobuf
     * @param url 
     * @param data 
     * @param encode 
     * @param decode 
     * @param handleError 
     * @param callback 
     * @param target 
     * @param isLog 
     * @returns 
     */
    public static async PostProto(url: string, data: any, encode: Function, decode: Function, handleError: Function, callback?: Function | null, target?: any, isLog: boolean = true): Promise<any> {
        return new Promise((resolve, reject) => {
            try {
                WWW.PostProtoEx(url, data, encode, decode, handleError, (res: any) => {
                    if (callback && target)
                        callback.call(target, res);
                    resolve(res);
                }, this, isLog);
            } catch (error) {
                console.error("请求失败：" + url + "=>" + error);
                resolve(null);
            }
        });
    }
}